package com.xiashitech.agent.instrumentation.spring.refresh;

import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.instrumentation.base.AbstractAttributesExtractor;
import com.xiashitech.agent.instrumentation.context.SpringApplicationContext;
import com.xiashitech.agent.instrumentation.spring.refresh.api.inst.XSSpringMVCAllApiDeal;
import com.xiashitech.agent.instrumentation.utils.MachineAttributesUtil;
import com.xiashitech.interfaces.agent.dto.api.Api;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.context.Context;
import org.jetbrains.annotations.Nullable;

import java.util.List;

public class XSSpringRefreshAttributesExtractor extends AbstractAttributesExtractor<Object,Void> {
    public String getAttributesExtractorName() {
        return XSSpringRefreshAttributesExtractor.class.getName();
    }

    /**
     * spring容器初始化之前
     * @param attributesBuilder
     * @param context
     * @param applicationContext
     */
    @Override
    public void onXSStart(AttributesBuilder attributesBuilder, Context context, Object applicationContext) {}

    /**
     * spring容器初始化之后
     * @param attributesBuilder
     * @param context
     * @param applicationContext
     * @param unused
     * @param throwable
     */
    @Override
    public void onXSEnd(AttributesBuilder attributesBuilder, Context context, Object applicationContext, @Nullable Void unused, @Nullable Throwable throwable) {
        try {
            /**
             * 将ApplicationContext保存到agent当前系统的全局上线文
             */
            System.out.println("###XSSpringRefreshAttributesExtractor000 enter");
            SpringApplicationContext.setApplicationContext(applicationContext);
            /**
             * 获取springboot启动配置的端口号
             */
            try {
                Object environment = applicationContext.getClass().getMethod("getEnvironment").invoke(applicationContext);
                String port = (String)environment.getClass().getMethod("getProperty",String.class).invoke(environment,"server.port");
                // String contextPath = (String)environment.getClass().getMethod("getProperty",String.class).invoke(environment,"server.servlet.context-path");
                // System.out.println("XSSpringRefreshAttributesExtractor: " + contextPath);
                attributesBuilder.put("xs.applicationContext.className ", applicationContext.getClass().getName() );
                if(port != null) {
                    attributesBuilder.put("xs.server.port", port);
                    SpringApplicationContext.setPort(port);
                }
            } catch (Throwable e) {
            }
            /**
             * 提取全量api，并同步到openmetadata中，中间会将全量api也同步记录到span属性里。
             */
            String applicationContextClassName = applicationContext.getClass().getName();
            System.out.println("###XSSpringRefreshAttributesExtractor003 applcationContextClassName: " + applicationContextClassName);
            if(applicationContextClassName.startsWith("org.springframework")
                    && applicationContextClassName.endsWith("ApplicationContext")
                    && Class.forName("org.springframework.context.support.AbstractApplicationContext").isAssignableFrom(applicationContext.getClass())) {
                System.out.println("XSSpringRefreshAttributesExtractor004 applcationContextClassName: " + applicationContextClassName);
            // if(applicationContext.getClass().getName().equals("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.boot.web.servlet.context.XmlServletWebServerApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.web.context.support.GenericWebApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.web.context.support.XmlWebApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext") ||
            //         applicationContext.getClass().getName().equals("org.springframework.context.annotation.AnnotationConfigApplicationContext")) {
                    List<Api> apis = XSSpringMVCAllApiDeal.extractApi(applicationContext);
                System.out.println("###XSSpringRefreshAttributesExtractor005 applcationContextClassName: " + applicationContextClassName);
                XSSpringMVCAllApiDeal.generateApisSpanAttr(apis,attributesBuilder);
                    XSSpringMVCAllApiDeal.syncApiToOpenMetadata(apis);
                System.out.println("###XSSpringRefreshAttributesExtractor006 applcationContextClassName: " + applicationContextClassName);
                XSSpringMVCAllApiDeal.syncApiToLocalCache(apis);
                System.out.println("###XSSpringRefreshAttributesExtractor007 applcationContextClassName: " + applicationContextClassName);
            }
        } catch (Throwable e) {
            e.printStackTrace();
            StartConfig.throwableStackPrinter(e);
        }
        MachineAttributesUtil.fillMachineAttributes(attributesBuilder);
        System.out.println("XSSpringRefreshAttributesExtractor008 attributesBuilder): " + attributesBuilder.toString());
    }


}
